;(function($) {
    'use strict';

    window.EWP = function(debug=false, callback=null) {
        var instance = new EwpPlug(debug);
        instance.init(callback);
        return instance;
    };

    function EwpPlug(debug) {
        this.debug = debug;
        this.wsUrl = 'ws://127.0.0.1:5847';
        this.busy = false;
        this.last_method = 'null';
        this.enable_computer_screen = false;
        this.apkVersion = '';
        this.serialNo = '';
        this.has_android_finger = true;
        this.has_android_idcardreader = true;
        this.has_android_multicardreader = false;
        this.has_android_doccamera = false;
        this.has_android_facecamera = true;
        this.has_android_facesdk = false;
        this.last_method = 'null';
        this.current_method = 'null';
        this.driver_err_msg = 'EWP外设驱动服务异常';

        this.camera_poster = "";
        this.card_poster = ""
        this.head_poster = ''

        this.init = function(callback) {
            var self = this;
            self.ws = null;
            this.ws = new WebSocket(self.wsUrl);
            self.ws.onerror = function(event) {
                if (self.debug) {
                    self.toast({ type: 'error', message: 'WebSocket未连接' });
                }
            };
            self.ws.onmessage = function(event) {
                console.log('Received message:', event.data);
                var response = JSON.parse(event.data);
                if (response.method === 'GetDevAndModulesInfo') {
                    if (response.retVal === 0) {
                        self.apkVersion = response.apkVersion;
                        self.serialNo = response.serialNo;
                        if (response.moduleState.includes('USB身份证阅读器')) {
                            self.has_android_idcardreader = false;
                        }
                        if (response.moduleState.includes('指纹模块')) {
                            self.has_android_finger = false;
                        }
                        if (!response.moduleState.includes('高拍仪文稿头')) {
                            self.has_android_doccamera = true;
                        }
                        if (response.moduleState.includes('高拍仪人像头')) {
                            self.has_android_facecamera = false;
                        }
                        if (!response.moduleState.includes('人脸识别算法授权')) {
                            self.has_android_facesdk = true;
                        }
                        self.wsReady = true;
						if (callback) {
							try {
								callback()
							} catch(err) {
								console.log(err)
							}
						}
                        // resolve(true);
                    } else {
                        self.has_android_finger = false;
                        self.has_android_idcardreader = false;
                        self.has_android_multicardreader = false;
                        self.has_android_doccamera = false;
                        self.has_android_facecamera = false;
                        self.has_android_facesdk = false;
                        self.wsReady = true;
						if (callback) {
							try {
								callback()
							} catch(err) {
								console.log(err)
							}
						}
                        // reject(new Error('初始化失败'));
                    }
                }
            };
            self.ws.onopen = function(event) {
                console.log('WebSocket连接已建立');
                var jsonObject = {
                    method: 'GetDevAndModulesInfo',
                    args: {
                        modules: '01身份证阅读器,02高拍仪人像头/双目彩色摄像头,03高拍仪文稿头,04宽动态摄像头,05双目黑白摄像头,06指纹模块,07多合一读卡器,08扫码器,09小票打印机,10人脸识别算法授权,11鱼眼摄像头'
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
            };
            self.ws.onclose = function(event) {
                self.ws = null;
                self.toast({ type: 'error', message: self.driver_err_msg });
                
                // reject(new Error('WebSocket连接错误'));
                // console.log('WebSocket连接已关闭, 正在尝试重连...');
                // setTimeout(function() {
                //     self.init();
                // }, 5000);
            };
        }

        this.setDriverErrMsg = function(msg) {
            this.driver_err_msg = msg;
        }

        this.handle = function(callback, check_busy=true) {
            const self = this;
            return new Promise((resolve, reject) => {
                var cc = 0;
                function fc() {
                    if (!self.wsReady) {
                        if (cc < 15) {
                            setTimeout(function() {
                                fc();
                                cc++;
                            }, 200);
                        } else {
                            if (!self.ws || self.ws.readyState !== WebSocket.OPEN) {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: 'WebSocket未连接' });
                                }
                                reject({ method: self.current_method, retVal: -1, errMsg: 'WebSocket未连接' });
                            } else {
                                if (check_busy) {
                                    if (self.busy) {
                                        if (self.debug) {
                                            self.toast({ type: 'error', message: '上一个操作未完成\nmethod: ' + self.last_method });
                                        }
                                        reject({ method: self.current_method, retVal: -1, errMsg: '上一个操作未完成\nmethod: ' + self.last_method });
                                    } else {
                                        self.busy = true;
                                        callback(resolve, reject);
                                    }
                                } else {
                                    callback(resolve, reject);
                                }
                            }
                        }
                        
                    } else {
                        if (check_busy) {
                            if (self.busy) {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: '上一个操作未完成\nmethod: ' + self.last_method });
                                }
                                reject({ method: self.current_method, retVal: -1, errMsg: '上一个操作未完成\nmethod: ' + self.last_method });
                            } else {
                                self.busy = true;
                                callback(resolve, reject);
                            }
                        } else {
                            callback(resolve, reject);
                        }
                    }
                }
                fc();
            });
        };

        // 投屏显示
        this.StartComputerScreen = function(options) {
            const self = this;
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'StartComputerScreen', args: {} };
                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'StartComputerScreen') {
                        self.busy = false;
                        if (response.retVal === 0) {
                        self.enable_computer_screen = true;
                            resolve(response);
                        } else {
                            self.enable_computer_screen = false;
                            reject(response);
                        }
                    }
                };
                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 读取序列号
        this.GetSerialNo = function(options) {
            const self = this;
            self.current_method = 'GetSerialNo';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'GetSerialNo', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'GetSerialNo') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type: 'success', message: '序列号: ' + response.serialNo });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '读取序列号失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 读取软件版本
        this.GetApkVersion = function(options) {
            const self = this;
            self.current_method = 'GetApkVersion';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'GetApkVersion', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'GetApkVersion') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type: 'success', message: '软件版本号: ' + response.apkVersion });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '读取软件版本失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 读取硬件ID
        this.GetDevID = function(options) {
            const self = this;
            self.current_method = 'GetDevID';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'GetDevID', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'GetDevID') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '硬件ID: '+ response.devID });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '读取硬件ID失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 暂停服务
        this.StopService = function(options) {
            const self = this;
            self.current_method = 'StopService';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'StopService', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'StopService') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '暂停服务成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '暂停服务失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 恢复服务
        this.RestoreService = function(options) {
            const self = this;
            self.current_method = 'RestoreService';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'RestoreService', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'RestoreService') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '恢复服务成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '恢复服务失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 设置音量
        this.SetVolume = function(options) {
            const self = this;
            self.current_method = 'SetVolume';
            var settings = $.extend({volume: 80}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'SetVolume', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'SetVolume') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '音量设置成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '设置音量失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 播放语音文件
        this.PlaySound = function(options) {
            const self = this;
            self.current_method = 'PlaySound';
            var settings = $.extend({soundFileName: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'PlaySound', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'PlaySound') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '播放成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '播放失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 软件升级
        this.UpdateApk = function(options) {
            const self = this;
            self.current_method = 'UpdateApk';
            var settings = $.extend({apkPath: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'UpdateApk', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'UpdateApk') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '软件升级成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -91;
                            if (self.debug) {
                                self.toast({ type: 'info', message: self.last_method + '已撤销操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '软件升级失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 员工登录
        this.LoginByHtml = function(options) {
            const self = this;
            self.current_method = 'LoginByHtml';
            var settings = $.extend({userName: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'LoginByHtml', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'LoginByHtml') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '登录成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '登录失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 业务评价
        this.EvaluateByHtml = function(options) {
            const self = this;
            self.current_method = 'EvaluateByHtml';
            var settings = $.extend({outTimes: 60}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'EvaluateByHtml', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'EvaluateByHtml') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '评价成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -91;
                            if (self.debug) {
                                self.toast({ type: 'info', message: self.last_method + '已撤销操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '评价失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 注销登录
        this.LogoutByHtml = function(options) {
            const self = this;
            self.current_method = 'LogoutByHtml';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'LogoutByHtml', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'LogoutByHtml') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: '注销成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: '注销失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 显示信息
        this.ShowInformation = function(options) {
            const self = this;
            self.current_method = 'ShowInformation';
            var settings = $.extend({outTimes: 60, isUrl: 0, showInfo: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowInformation', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowInformation') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: self.last_method + '推送成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '推送失败: ' + response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 确认信息
        this.ShowAndConfirmInformation = function(options) {
            const self = this;
            self.current_method = 'ShowAndConfirmInformation';
            var settings = $.extend({outTimes: 60, isUrl: 0, showInfo: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowAndConfirmInformation', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowAndConfirmInformation') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (response.confirmResult === 4) {
                                response.retVal = -91;
                                response.errMsg = '已取消操作';
                                if (self.debug) {
                                    self.toast({ type: 'info', message: self.last_method + '已撤销操作' });
                                }
                                reject(response);
                            } else if (response.confirmResult === 2) {
                                response.retVal = -92;
                                response.errMsg = '已取消操作';
                                if (self.debug) {
                                    self.toast({ type: 'info', message: self.last_method + '用户已取消操作' });
                                }
                                reject(response);
                            } else {
                                if (self.debug) {
                                    self.toast({ type:'success', message: self.last_method + '推送成功' });
                                }
                                resolve(response);
                            }
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '推送失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 确认PDF
        this.ShowPdfAndConfirm = function(options) {
            const self = this;
            self.current_method = 'ShowPdfAndConfirm';
            var settings = $.extend({outTimes: 60, dataForm: 1, fileData: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowPdfAndConfirm', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowPdfAndConfirm') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (response.confirmResult === 2) {
                                response.retVal = -92;
                                response.errMsg = '已取消操作';
                                if (self.debug) {
                                    self.toast({ type: 'info', message: self.last_method + '用户已取消操作' });
                                }
                                reject(response);
                            } else {
                                if (self.debug) {
                                    self.toast({ type:'success', message: self.last_method + '推送成功' });
                                }
                                resolve(response);
                            }
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '推送失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 显示图片-展示收款二维码
        this.ShowPictures = function(options) {
            const self = this;
            self.current_method = 'ShowPictures';
            var settings = $.extend({outTimes: 60, showType: 1, fileForm: 1, fileData: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowPictures', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowPictures') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: self.last_method + '推送成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -91;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: self.last_method + '已撤销操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '推送失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 推送付款链接
        this.GenerateQRCode = function(options) {
            const self = this;
            self.current_method = 'GenerateQRCode';
            var settings = $.extend({outTimes: 60, qrContent: ""}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'GenerateQRCode', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'GenerateQRCode') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: self.last_method + '推送成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '推送失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // ========================================================================================================

        // 获取签名
        this.GetSignName = function(options) {
            const self = this;
            var settings = $.extend({outTimes: 60}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'GetSignName_Base64', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'GetSignName_Base64') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: 'GetSignName签署成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'GetSignName用户已取消操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 获取签名 (含预览)
        this.SignNameScreen = function(options) {
            const self = this;
            var settings = $.extend({outTimes: 60}, options);
            return this.handle((resolve, reject) => {
                var previews = self.getPreviewElements(settings);

                var jsonObject = { method: 'SignNameScreen_Start', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'SignNameScreen_Start') {
                        if (response.retVal === 0) {
                            self.ws.send(JSON.stringify({ method: 'SignNameScreen_Status', args: {} }));
                            self.last_method = 'SignNameScreen_Status';
                        } else {
                            self.restoreScreen();

                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else if (response.method === 'ScreenStream') {
                        if (response.imgBase64 != null) {
                            for (let i = 0; i < previews.length; i++) {
                                previews[i].src = "data:image/jpeg;base64," + response.imgBase64;
                            }
                        }
                    } else if (response.method === 'SignNameScreen_Status') {
                        if (response.signScreenStatus == 0) {
                            self.restoreScreen();

                            if (self.debug) {
                                self.toast({ type:'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        } else if (response.signScreenStatus == 1) {
                            setTimeout(function() {
                                self.ws.send(JSON.stringify({ method: 'SignNameScreen_Status', args: {} }));
                                self.last_method = 'SignNameScreen_Status';
                            }, 1000);
                        } else if (response.signScreenStatus == 2) {
                            self.ws.send(JSON.stringify({ method: 'SignNameScreen_Get', args: {} }));
                            self.last_method = 'SignNameScreen_Get';
                        } else if (response.signScreenStatus == 3) {
                            self.restoreScreen();

                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'SignNameScreen用户已取消操作' });
                            }
                            reject(response);
                            // if (self.debug) {
                            //     self.toast({ type:'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            // }
                            // reject(new Error(response.errMsg || '签字失败, 或意外中断'));
                        }
                    } else if (response.method === 'SignNameScreen_Get') {
                        if (response.retVal === 0) {
                            for (let i = 0; i < previews.length; i++) {
                                previews[i].result = response.signPicBase64
                            }
                            self.ws.send(JSON.stringify({ method: 'SignNameScreen_Stop', args: {} }));
                            self.last_method = 'SignNameScreen_Stop';
                        } else {
                            self.restoreScreen();

                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else if (response.method === 'SignNameScreen_Stop') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            for (let i = 0; i < previews.length; i++) {
                                response.signPicBase64 = previews[i].result
                            }
                            if (self.debug) {
                                self.toast({ type:'success', message: 'SignNameScreen签署成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        } 
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 显示文档并核签 (不合成)
        this.SignDocument = function(options) {
            const self = this;
            self.current_method = 'SignDocument';
            var settings = $.extend({outTimes: 60, fileForm: 1, fileData: "", signType: 1}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowPdfSignOrFinger_Base64', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowPdfSignOrFinger_Base64') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: 'SignDocument签署成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'SignDocument用户已取消操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 显示文档并核签 (按坐标合成)
        this.SignDocumentByCoordinates = function(options) {
            const self = this;
            self.current_method = 'SignDocumentByCoordinates';
            var settings = $.extend({outTimes: 60, docType: 0, fileForm: 1, fileData: "", signType: 1, sPos: "[]"}, options);
            settings.dataForm = settings.fileForm;
            delete settings.fileForm;
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowDocumentSignOrFingerCoordinates_Base64', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowDocumentSignOrFingerCoordinates_Base64') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: 'SignDocumentByCoordinates签署成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'SignDocumentByCoordinates用户已取消操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 显示文档并核签 (按点击位置合成)
        this.SignDocumentByTouch = function(options) {
            const self = this;
            self.current_method = 'SignDocumentByTouch';
            var settings = $.extend({outTimes: 60, docType: 0, fileForm: 1, fileData: "", signType: 1}, options);
            settings.dataForm = settings.fileForm;
            delete settings.fileForm;
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ShowDocumentSignOrFingerPoints_Base64', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ShowDocumentSignOrFingerPoints_Base64') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                self.toast({ type:'success', message: 'SignDocumentByTouch签署成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'SignDocumentByTouch用户已取消操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '签署失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // ========================================================================================================

        // 扫码
        this.ReadCode = function(options) {
            const self = this;
            self.current_method = 'ReadCode';
            var settings = $.extend({outTimes: 60}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'ReadQR_Yuanjie', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'ReadQR') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            response.method = 'ReadCode';
                            if (self.debug) {
                                self.toast({ type:'success', message: 'ReadCode读取成功' });
                            }
                            resolve(response);
                        } else if (response.retVal === -9) {
                            response.retVal = -92;
                            response.errMsg = '已取消操作';
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'ReadCode用户已取消操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '读取失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 读取身份证
        this.ReadIDCard = function(options) {
            const self = this;
            self.current_method = 'ReadIDCard';
            var settings = $.extend({outTimes: 60, cardReader: 0}, this.settings, options);
            return this.handle((resolve, reject) => {
                if (self.has_android_idcardreader) {
                    var jsonObject = { method: 'ReadIDCard_Base64', args: settings };
                } else if (self.has_android_multicardreader) {
                    settings.cardReader = 1;
                    var jsonObject = { method: 'ReadIDCard_Base64', args: settings };
                } else {
                    var jsonObject = { method: 'SDT_ReadIDCard', args: settings }; 
                }
                var fail_count = 0;

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (['ReadIDCard_Base64', 'SDT_ReadIDCard', 'iReadIdentityCard'].includes(response.method)) {
                        if (response.method === 'SDT_ReadIDCard' && response.retVal === -3) {
                            self.ws.send(JSON.stringify({ method: 'iReadIdentityCard', args: {} }));
                            self.last_method = 'iReadIdentityCard';
                        } else if (response.method === 'iReadIdentityCard' && response.retVal === -145 && fail_count < (settings.outTimes/3)) {
                            setTimeout(function() {
                                fail_count++;
                                self.ws.send(JSON.stringify({ method: 'iReadIdentityCard', args: {} }));
                                self.last_method = 'iReadIdentityCard';
                            }, 3000);
                        } else {
                            self.restoreScreen();
                            
                            if (response.retVal === 0) {
                                if (response.method === 'ReadIDCard_Base64') {
                                    response.idInfo = response.idInfo.data;
                                    response.headPicBase64 = response.idPhotoPicBase64;
                                    response.FrontPicBase64 = response.idPositivePicBase64;
                                    response.BackPicBase64 = response.idNegativePicBase64;
                                } else if (response.method === 'SDT_ReadIDCard') {
                                    let b = response.idInfo.split('|');
                                    response.idInfo = { name: b[0], sex: b[1], nations: b[2], birthday: b[3], address: b[4], id_num: b[5], maker: b[6], startData: b[7], endData: b[8] }
                                    response.headPicBase64 = response.idPhotoBase64;
                                    response.FrontPicBase64 = response.idFrontPhotoBase64;
                                    response.BackPicBase64 = response.idBackPhotoBase64;
                                } else if (response.method === 'iReadIdentityCard') {
                                    let c = response.idCardInfo.split('|');
                                    response.idInfo = { name: c[0], sex: c[1], nations: c[2], birthday: c[3], address: c[4], id_num: c[5], maker: c[6], startData: c[7], endData: c[8] }
                                    response.headPicBase64 = response.photoBase64;
                                    response.FrontPicBase64 = response.photoFrontBase64;
                                    response.BackPicBase64 = response.photoBackBase64;
                                }
                                if (self.debug) {
                                    self.toast({ type:'success', message: 'ReadIDCard读取成功' });
                                }
                                resolve({
                                    method: 'ReadIDCard',
                                    retVal: response.retVal,
                                    errMsg: response.errMsg,
                                    cardInfo: {
                                        name: response.idInfo.name,
                                        sex: response.idInfo.sex,
                                        nation: response.idInfo.nations,
                                        birth: response.idInfo.birthday,
                                        address: response.idInfo.address,
                                        idNum: response.idInfo.id_num,
                                        authority: response.idInfo.maker,
                                        validDate: response.idInfo.startData + '-' + response.idInfo.endData
                                    },
                                    headPicBase64: response.headPicBase64,
                                    FrontPicBase64: response.FrontPicBase64,
                                    BackPicBase64: response.BackPicBase64
                                });
                            } else if (response.retVal === -9) {
                                response.retVal = -92;
                                response.errMsg = '已取消操作';
                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'ReadIDCard用户已取消操作' });
                                }
                                reject(response);
                            } else {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '读取失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 获取指纹
        this.GetFingerPrint = function(options) {
            const self = this;
            self.current_method = 'GetFingerPrint';
            var settings = $.extend({outTimes: 60, picWidth: 256, picHeight: 360}, options);
            return this.handle((resolve, reject) => {
                if (self.has_android_finger) {
                    var jsonObject = { method: 'GetFingerPrint_Base64', args: settings };
                } else {
                    var jsonObject = { method: 'GetFingerPrint_PC', args: settings }; 
                }

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (['GetFingerPrint_Base64', 'GetFingerPrint_PC'].includes(response.method)) {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (response.method === 'GetFingerPrint_Base64') {
                                response.fingerPicBase64 = response.fingerPicPathBase64
                            }
                            if (self.debug) {
                                self.toast({ type:'success', message: 'GetFingerPrint读取成功' });
                            }
                            resolve({
                                method: 'GetFingerPrint',
                                retVal: response.retVal,
                                errMsg: response.errMsg,
                                fingerPicBase64: response.fingerPicBase64
                            });
                        } else if (response.retVal === -9) {
                            response.retVal = -91;
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'GetFingerPrint已撤销操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '读取失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            });
        };

        // 获取人像
        this.GetHeadPhoto = function(options) {
            const self = this;
            self.current_method = 'GetHeadPhoto';
            var settings = $.extend({outTimes: 60, shootType: 0}, this.settings, options);
            return this.handle((resolve, reject) => {
                function usbDeviceFunc(resolve, reject) {
                    var jsonObject = { method: 'GetPhoto_Base64', args: { outTimes: settings.outTimes } };
    
                    self.ws.onmessage = function(event) {
                        var response = JSON.parse(event.data);
                        if (response.method === 'GetPhoto_Base64') {
                            self.restoreScreen();
                            if (response.retVal === 0) {
                                response.method = 'GetHeadPhoto';
                                if (self.debug) {
                                    self.toast({ type:'success', message: 'GetHeadPhoto获取成功' });
                                }
                                resolve(response);
                            } else if (response.retVal === -9) {
                                response.retVal = -91;
                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'GetHeadPhoto已撤销操作' });
                                }
                                reject(new Error('已撤销操作'));
                            } else {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '获取失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        }
                    };
    
                    self.ws.send(JSON.stringify(jsonObject));
                    self.last_method = jsonObject.method;
                }
    
                function openDialog(resolve, reject) {
                    // 启动弹窗拍摄人像的方式
                    var mask = self.createMask();
    
                    // 创建弹窗容器
                    var dialog = document.createElement('div');
                    dialog.setAttribute('style', 'position: fixed; top: 40%; left: 50%; width: 460px; height: 300px; transform: translate(-50%, -50%); background-color: #fff; padding: 24px; border-radius: 5px; z-index: 2050;');
    
                    var preview = document.createElement('img');
                    preview.setAttribute('style', 'width: 320px; height: 240px; margin-left: 50%; margin-bottom: 24px; transform: translate(-50%, 0); border: 1px dashed #dcdfe6; border-radius: 5px;');
                    preview.src = self.camera_poster
                    dialog.appendChild(preview);
                    
                    // 创建取消按钮
                    var cancelBtn = document.createElement('button');
                    cancelBtn.textContent = '取消';
                    cancelBtn.setAttribute('style', 'width: 60px; height: 32px; margin-left: calc(50% - 60px - 16px); background-color: #f2f3f5; color: #4e5969; border: none; border-radius: 2px;');
                    cancelBtn.onmouseover = function() {
                        cancelBtn.style.backgroundColor = '#e6e8eb';
                    };
                    cancelBtn.onmouseout = function() {
                        cancelBtn.style.backgroundColor = '#f2f3f5'; 
                    }
                    cancelBtn.onclick = function() {
                        cancelBtn.disabled = true;
                        submitBtn.disabled = true;
                        self.ws.send(JSON.stringify({"method": "VideoStop", "args": {}}));
                        self.last_method = 'VideoStop';
                    };
                    dialog.appendChild(cancelBtn);
    
                    var submitBtn = document.createElement('button');
                    submitBtn.textContent = '拍照';
                    submitBtn.setAttribute('style', 'width: 60px; height: 32px; margin-left: 32px; background-color: #165dff; color: #ffffff; border: none; border-radius: 2px;');
                    submitBtn.onmouseover = function() {
                        submitBtn.style.backgroundColor = '#0940c9'; 
                    }
                    submitBtn.onmouseout = function() {
                        submitBtn.style.backgroundColor = '#165dff'; 
                    }
                    submitBtn.disabled = true;
                    dialog.appendChild(submitBtn);
    
                    submitBtn.onclick = function() {
                        cancelBtn.disabled = true;
                        submitBtn.disabled = true;
                        self.ws.onmessage = function(event) {
                            var response = JSON.parse(event.data);
                            if (response.method === 'VideoStop') {
                                self.removeElement(mask);
                                self.removeElement(dialog);
        
                                self.restoreScreen();

                                if (self.debug) {
                                    self.toast({ type:'success', message: 'GetHeadPhoto获取成功' });
                                }
                                resolve({
                                    method: 'GetHeadPhoto',
                                    retVal: response.retVal,
                                    headPicBase64: preview.src.replace('data:image/png;base64,', ''),
                                    errMsg: '成功'
                                });
                            }
                            
                        }
                        self.ws.send(JSON.stringify({"method": "VideoStop", "args": {}}));
                        self.last_method = 'VideoStop';
                    };
    
                    self.ws.onmessage = function(event) {
                        var response = JSON.parse(event.data);
                        if (response.method === 'VideoStart') {
                            if (response.retVal === 0) {
                                document.body.appendChild(mask);
                                document.body.appendChild(dialog);
                                submitBtn.disabled = false;
                            } else {
                                self.busy = false;
                                if (self.enable_computer_screen) {
                                    self.StartComputerScreen();
                                }

                                response.method = 'GetHeadPhoto';
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '获取失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        } else if (response.method === 'VideoStream') {
                            preview.src = 'data:image/png;base64,' + response.imgBase64;
                        } else if (response.method === 'VideoStop') {
                            self.removeElement(mask);
                            self.removeElement(dialog);
    
                            self.restoreScreen();

                            if (self.debug) {
                                self.toast({ type: 'info', message: 'GetHeadPhoto已撤销操作' });
                            }
                            reject({ method: 'GetHeadPhoto', retVal: -91, errMsg: '已撤销操作' });
                        }
                    };
    
                    self.ws.send(JSON.stringify({"method": "VideoStart", "args": {"cameraNo": 2, "isEdgeDetection": 0}}));
                    self.last_method = "VideoStart";
                }

                if (settings.shootType === 1) {
                    usbDeviceFunc(resolve, reject);
                } else if (settings.shootType === 2) {
                    openDialog(resolve, reject);
                } else if (self.has_android_facecamera && self.has_android_facesdk) {
                    usbDeviceFunc(resolve, reject);
                } else if (self.has_android_facecamera && !self.has_android_facesdk) {
                    openDialog(resolve, reject);
                } else if (!self.has_android_facecamera) {
                    openDialog(resolve, reject);
                } else {
                    self.restoreScreen();

                    if (self.debug) {
                        self.toast({ type: 'error', message: '不支持的调用方式, 请检测模块是否正常' });
                    }
                    reject(new Error('不支持的调用方式, 请检测模块是否正常')); 
                }
            });
        };

        // 人证比对
        this.FaceValidateWithIDCard = function(options) {
            const self = this;
            self.current_method = 'FaceValidateWithIDCard';
            var settings = $.extend({outTimes: 60, shootType: 0}, this.settings, options);
            return this.handle((resolve, reject) => {
                function usbDeviceFunc(resolve, reject) {
                    // 判断读卡器的类型及连接方式
                    if (self.has_android_idcardreader) {
                        var jsonObject = { method: 'FaceValidateWithIdCard', args: { cardReader: 0, outTimes: settings.outTimes, cameraType: 0 } };
                    } else if (self.has_android_multicardreader) {
                        var jsonObject = { method: 'FaceValidateWithIdCard', args: { cardReader: 1, outTimes: settings.outTimes, cameraType: 0 } };
                    } else {
                        var jsonObject = { method: 'GetPhoto_Base64', args: { outTimes: settings.outTimes } };
                    }

                    self.ws.onmessage = async function(event) {
                        var response = JSON.parse(event.data);
                        if (response.method === 'FaceValidateWithIdCard') {
                            self.restoreScreen();

                            if (response.retVal === 0) {
                                if (self.debug) {
                                    if (response.score > 0.7) {
                                        self.toast({ type:'success', message: 'FaceValidateWithIDCard核对通过' });
                                    } else {
                                        self.toast({ type: 'info', message: 'FaceValidateWithIDCard核验不通过: 相似度' + response.score });
                                    }
                                }
                                resolve({
                                    method: 'FaceValidateWithIDCard',
                                    retVal: response.retVal,
                                    score: response.score,
                                    headPicBase64: response.idPhotoBase64,
                                    scencePicBase64: response.scenceBase64,
                                    errMsg: '成功'
                                })
                            } else if (response.retVal === -9) {
                                response.retVal = -91;
                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'FaceValidateWithIDCard已撤销操作' });
                                }
                                reject(response);
                            } else {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        } else if (response.method === 'GetPhoto_Base64') {
                            if (response.retVal === 0) {
                                var screenPicBase64 = response.photoBase64;

                                self.busy = false;
                                let d = self.debug;
                                self.debug = false;
                                let t = self.enable_computer_screen;
                                self.enable_computer_screen = false;
                                try {
                                    var i = await self.ReadIDCard({ outTimes: settings.outTimes })
                                } catch (error) {
                                    var i = { retVal: -1, errMsg: error.toString() }
                                }
                                self.busy = true;
                                self.debug = d;
                                self.enable_computer_screen = t;
                                if (i.retVal === 0) {
                                    var jsonObject = { method: 'FaceValidateWithTwoPhotos', args: { fileForm: 1, file1Data: screenPicBase64, file2Data: i.headPicBase64, outTimes: settings.outTimes } };
                                
                                    self.ws.onmessage = function(event) {
                                        var response = JSON.parse(event.data);
                                        self.busy = false;
                                        if (self.enable_computer_screen) {
                                            self.StartComputerScreen();
                                        }
                                        if (response.retVal === 0) {
                                            if (self.debug) {
                                                if (response.score > 0.7) {
                                                    self.toast({ type:'success', message: 'FaceValidateWithIDCard核对通过' });
                                                } else {
                                                    self.toast({ type: 'info', message: 'FaceValidateWithIDCard核验不通过: 相似度' + response.score });
                                                }
                                            }
                                            resolve({
                                                method: 'FaceValidateWithIDCard',
                                                retVal: response.retVal,
                                                score: response.score,
                                                headPicBase64: i.headPicBase64,
                                                scencePicBase64: screenPicBase64,
                                                errMsg: '成功'
                                            })
                                        } else if (response.retVal === -9) {
                                            response.retVal = -91;
                                            if (self.debug) {
                                                self.toast({ type: 'info', message: 'FaceValidateWithIDCard已撤销操作' });
                                            }
                                            reject(response);
                                        } else {
                                            if (self.debug) {
                                                self.toast({ type: 'error', message: self.last_method + '比对失败: '+ response.errMsg });
                                            }
                                            reject(response);
                                        }
                                    }
                                    
                                    self.ws.send(JSON.stringify(jsonObject));
                                    self.last_method = jsonObject.method;
                                } else if (response.retVal === -9) {
                                    self.busy = false;
                                    if (self.enable_computer_screen) {
                                        self.StartComputerScreen();
                                    }

                                    response.retVal = -91;
                                    if (self.debug) {
                                        self.toast({ type: 'info', message: 'FaceValidateWithIDCard已撤销操作' });
                                    }
                                    reject(response);
                                } else {
                                    self.busy = false;
                                    if (self.enable_computer_screen) {
                                        self.StartComputerScreen();
                                    }
                
                                    if (self.debug) {
                                        self.toast({ type: 'error', message: 'FaceValidateWithIDCard读取证件失败' });
                                    }
                                    reject(response);
                                }
                            } else if (response.retVal === -9) {
                                self.busy = false;
                                if (self.enable_computer_screen) {
                                    self.StartComputerScreen();
                                }

                                response.retVal = -91;
                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'FaceValidateWithIDCard已撤销操作' });
                                }
                                reject(response);
                            } else {
                                self.busy = false;
                                if (self.enable_computer_screen) {
                                    self.StartComputerScreen();
                                }
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '获取失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    };

                    self.ws.send(JSON.stringify(jsonObject));
                    self.last_method = jsonObject.method;
                }

                async function openDialog(self, resolve, reject) {
                    // 启动弹窗拍摄人像的方式
                    var mask = self.createMask();

                    // 创建弹窗容器
                    var dialog = document.createElement('div');
                    dialog.setAttribute('style', 'display: flex; position: fixed; top: 40%; left: 50%; width: 560px; height: 300px; transform: translate(-50%, -50%); background-color: #fff; padding: 24px; border-radius: 5px; z-index: 2050;');

                    var preview = document.createElement('img');
                    preview.setAttribute('style', 'width: 280px; height: 294px; border: 1px dashed #dcdfe6; border-radius: 5px;');
                    preview.src = self.card_poster;

                    dialog.appendChild(preview);

                    var container = document.createElement('div');
                    container.setAttribute('style', 'width: 280px; height: 294px; margin-top: 6px; display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; position: relative;');
                    container.innerHTML = `
                        <div style="margin-bottom: 12px; margin-left: 18px;">
                            <label style="display: inline-block;width: 72px;height: 26px;vertical-align: middle;">姓名:</label>
                            <input class="idcard-name" style="width: 172px; vertical-align: middle; padding-left: 4px; border: none; background-color: #e8e8e8; height: 26px; border-radius: 3px;" readonly>
                        </div>
                        <div style="margin-bottom: 12px; margin-left: 18px;">
                            <label style="display: inline-block;width: 72px;height: 26px;vertical-align: middle;">性别:</label>
                            <div style="display: inline-block; width: 180px; height: 26px; border-radius: 3px; line-height: 26px;">
                                <label style="margin-left: 20px; cursor: not-allowed;">
                                    <input type="radio" name="gender" value="男" style="margin-right: 5px;" disabled>男
                                </label>
                                <label style="margin-left: 20px; cursor: not-allowed;">
                                    <input type="radio" name="gender" value="女" style="margin-right: 5px;" disabled>女
                                </label>
                            </div>
                        </div>
                        <div style="margin-bottom: 12px; margin-left: 18px;">
                            <label style="display: inline-block;width: 72px;height: 26px;vertical-align: middle;">民族:</label>
                            <input class="idcard-nation" style="width: 172px; vertical-align: middle; padding-left: 4px; border: none; background-color: #e8e8e8; height: 26px; border-radius: 3px;" readonly>
                        </div>
                        <div style="margin-bottom: 12px; margin-left: 18px;">
                            <label style="display: inline-block;width: 72px;height: 26px;vertical-align: middle;">身份证号:</label>
                            <input class="idcard-number" style="width: 172px; vertical-align: middle; padding-left: 4px; border: none; background-color: #e8e8e8; height: 26px; border-radius: 3px;" readonly>
                        </div>
                        <div style="margin-left: 18px;">
                            <div style="width: 260px; height: 80px; display: flex; align-items: center; justify-content: center;">
                                <img class="idcard-head" src=${self.head_poster} style="max-width: 100%; max-height: 100%;">
                            </div>
                        </div>
                    `

                    dialog.appendChild(container);

                    var cancelBtn = document.createElement('button');
                    cancelBtn.textContent = '取消';
                    cancelBtn.setAttribute('style', 'width: 60px; height: 32px; position: absolute; bottom: 0; right: 0; background-color: #f2f3f5; color: #4e5969; border: none; border-radius: 2px;');
                    cancelBtn.onmouseover = function() {
                        cancelBtn.style.backgroundColor = '#e6e8eb';
                    };
                    cancelBtn.onmouseout = function() {
                        cancelBtn.style.backgroundColor = '#f2f3f5'; 
                    }
                    cancelBtn.onclick = function() {
                        self.CancelOpt();
                        self.busy = false;
                        if (self.enable_computer_screen) {
                            self.StartComputerScreen();
                        }
                        
                        self.removeElement(mask);
                        self.removeElement(dialog);

                        if (self.debug) {
                            self.toast({ type: 'info', message: 'FaceValidateWithIDCard用户已取消操作' });
                        }
                        reject({ method: 'FaceValidateWithIDCard', retVal: -91, errMsg: '用户已取消操作' });
                    };
                    container.appendChild(cancelBtn);

                    var submitBtn = document.createElement('button');
                    submitBtn.textContent = '比对';
                    submitBtn.setAttribute('style', 'position: absolute; bottom: 0; right: 0; width: 60px; height: 32px; margin-left: 32px; background-color: #165dff; color: #ffffff; border: none; border-radius: 2px;');
                    submitBtn.onmouseover = function() {
                        submitBtn.style.backgroundColor = '#0940c9'; 
                    }
                    submitBtn.onmouseout = function() {
                        submitBtn.style.backgroundColor = '#165dff'; 
                    }
                    submitBtn.disabled = true;

                    document.body.appendChild(mask);
                    document.body.appendChild(dialog);

                    self.busy = false;
                    let d = self.debug;
                    self.debug = false;
                    let t = self.enable_computer_screen;
                    self.enable_computer_screen = false;
                    try {
                        var i = await self.ReadIDCard({ outTimes: settings.outTimes })
                    } catch (error) {
                        var i = { retVal: -1, errMsg: error.toString() }
                    }
                    self.busy = true;
                    self.debug = d;
                    self.enable_computer_screen = t;
                    if (i.retVal === 0) {
                        preview.src = self.camera_poster;
                        $('.idcard-name').val(i.cardInfo.name);
                        if (i.cardInfo.sex === '男') {
                            $('input[name="gender"][value="男"]').prop('checked', true);
                        } else {
                            $('input[name="gender"][value="女"]').prop('checked', true);
                        }
                        $('.idcard-nation').val(i.cardInfo.nation);
                        $('.idcard-number').val(i.cardInfo.idNum);
                        $('.idcard-head').attr('src', 'data:image/jpeg;base64,' + i.headPicBase64);
                        
                        self.ws.onmessage = function(event) {
                            var response = JSON.parse(event.data);
                            if (response.method === 'VideoStart') {
                                if (response.retVal === 0) {
                                    cancelBtn.style.right = '72px';
                                    submitBtn.onclick = function() {
                                        cancelBtn.disabled = true;
                                        submitBtn.disabled = true;
                                        self.ws.onmessage = function(event) {
                                            var response = JSON.parse(event.data);
                                            if (response.method === 'VideoStop') {
                                                self.ws.send(JSON.stringify({ method: 'FaceValidateWithTwoPhotos', args: { fileForm: 1, file1Data: preview.src.replace('data:image/png;base64,', ''), file2Data: i.headPicBase64, outTimes: settings.outTimes } }));
                                                self.last_method = 'FaceValidateWithTwoPhotos';
                                            } else if (response.method === 'FaceValidateWithTwoPhotos') {
                                                document.body.removeChild(mask);
                                                document.body.removeChild(dialog);
                    
                                                self.busy = false;
                                                if (self.enable_computer_screen) {
                                                    self.StartComputerScreen();
                                                }
                                                if (response.retVal === 0) {
                                                    if (self.debug) {
                                                        if (response.score > 0.7) {
                                                            self.toast({ type:'success', message: 'FaceValidateWithIDCard核对通过' });
                                                        } else {
                                                            self.toast({ type: 'info', message: 'FaceValidateWithIDCard核验不通过: 相似度' + response.score });
                                                        }
                                                    }
                                                    resolve({
                                                        method: 'FaceValidateWithIDCard',
                                                        retVal: response.retVal,
                                                        score: response.score,
                                                        headPicBase64: i.headPicBase64,
                                                        scencePicBase64: preview.src.replace('data:image/png;base64,', ''),
                                                        errMsg: '成功'
                                                    })
                                                } else if (response.retVal === -9) {
                                                    response.retVal = -91;
                                                    if (self.debug) {
                                                        self.toast({ type: 'info', message: 'FaceValidateWithIDCard已撤销操作' });
                                                    }
                                                    reject(response);
                                                } else {
                                                    if (self.debug) {
                                                        self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                                    }
                                                    reject(response);
                                                }
                                            }
                                        }
                                        self.ws.send(JSON.stringify({ method: 'VideoStop', args: {} }));
                                        self.last_method = 'VideoStop';
                                    };
                                    container.appendChild(submitBtn);
                                    submitBtn.disabled = false;
                                } else {
                                    self.busy = false;
                                    if (self.enable_computer_screen) {
                                        self.StartComputerScreen();
                                    }

                                    if (self.debug) {
                                        self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                    }
                                    reject(response);
                                }
                            } else if (response.method === 'VideoStream') {
                                preview.src = 'data:image/png;base64,' + response.imgBase64;
                            } else if (response.method === 'VideoStop') {
                                self.removeElement(mask);
                                self.removeElement(dialog);

                                self.busy = false;
                                if (self.enable_computer_screen) {
                                    self.StartComputerScreen();
                                }

                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'FaceValidateWithIDCard用户已取消操作' });
                                }
                                reject({ method: 'FaceValidateWithIDCard', retVal: -91, errMsg: '用户已取消操作' });
                            }
                        };

                        cancelBtn.onclick = function() {
                            cancelBtn.disabled = true;
                            submitBtn.disabled = true;
                            self.ws.send(JSON.stringify({ method: 'VideoStop', args: {} }));
                            self.ws.last_method = "VideoStop";
                        };
        
                        self.ws.send(JSON.stringify({"method": "VideoStart", "args": {"cameraNo": 2, "isEdgeDetection": 0}}));
                        self.last_method = "VideoStart";
                    } else {
                        self.busy = false;
                        if (self.enable_computer_screen) {
                            self.StartComputerScreen();
                        }

                        self.removeElement(mask);
                        self.removeElement(dialog);

                        if (self.debug) {
                            self.toast({ type: 'error', message: 'FaceValidateWithIDCard读取证件失败' });
                        }
                        reject({ method: 'FaceValidateWithIDCard', retVal: -93, errMsg: '读取证件失败' });
                    }
                }

                if (settings.shootType === 1) {
                    usbDeviceFunc(resolve, reject);
                } else if (settings.shootType === 2) {
                    openDialog(self, resolve, reject);
                } else if (self.has_android_facecamera && self.has_android_facesdk) {
                    usbDeviceFunc(resolve, reject);
                } else if (self.has_android_facecamera && !self.has_android_facesdk) {
                    openDialog(self, resolve, reject);
                } else if (!self.has_android_facecamera) {
                    openDialog(self, resolve, reject);
                } else {
                    self.busy = false;
                    if (self.enable_computer_screen) {
                        self.StartComputerScreen();
                    }
                    if (self.debug) {
                        self.toast({ type: 'error', message: '不支持的调用方式, 请检测模块是否正常' });
                    }
                    reject(new Error('不支持的调用方式, 请检测模块是否正常')); 
                }
            });
        };

        // 人照比对
        this.FaceValidateWithPhoto = function(options) {
            const self = this;
            self.current_method = 'FaceValidateWithPhoto';
            var settings = $.extend({outTimes: 60, shootType: 0, fileForm: 1}, this.settings, options);
            return this.handle((resolve, reject) => {
                function usbDeviceFunc(resolve, reject) {
                    var jsonObject = { method: 'FaceValidateWithPhoto', args: settings };

                    self.ws.onmessage = async function(event) {
                        var response = JSON.parse(event.data);
                        if (response.method === 'FaceValidateWithPhoto') {
                            self.restoreScreen();
                            
                            if (response.retVal === 0) {
                                if (self.debug) {
                                    if (response.score > 0.7) {
                                        self.toast({ type:'success', message: 'FaceValidateWithPhoto核对通过' });
                                    } else {
                                        self.toast({ type: 'info', message: 'FaceValidateWithPhoto核验不通过: 相似度' + response.score });
                                    }
                                }
                                resolve({
                                    method: 'FaceValidateWithPhoto',
                                    retVal: response.retVal,
                                    score: response.score,
                                    scencePicBase64: response.scencePicBase64,
                                    errMsg: '成功'
                                })
                            } else if (response.retVal === -9) {
                                response.retVal = -91;
                                if (self.debug) {
                                    self.toast({ type: 'info', message: 'FaceValidateWithPhoto已撤销操作' });
                                }
                                reject(response);
                            } else {
                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        }
                    };

                    self.ws.send(JSON.stringify(jsonObject));
                    self.last_method = jsonObject.method;
                }

                async function openDialog(self, resolve, reject) {
                    // 启动弹窗拍摄人像的方式
                    var mask = self.createMask();

                    // 创建弹窗容器
                    var dialog = document.createElement('div');
                    dialog.setAttribute('style', 'display: flex; position: fixed; top: 40%; left: 50%; width: 560px; height: 300px; transform: translate(-50%, -50%); background-color: #fff; padding: 24px; border-radius: 5px; z-index: 2050;');

                    var preview = document.createElement('img');
                    preview.setAttribute('style', 'width: 280px; height: 294px; border: 1px dashed #dcdfe6; border-radius: 5px;');
                    preview.src = self.camera_poster;

                    dialog.appendChild(preview);

                    var container = document.createElement('div');
                    container.setAttribute('style', 'width: 280px; height: 294px; margin-top: 6px; display: flex; flex-direction: column; align-items: flex-start; justify-content: flex-start; position: relative;');
                    container.innerHTML = `
                        <div style="margin-left: 18px;">
                            <div style="width: 260px; height: 246px; display: flex; align-items: center; justify-content: center;">
                                <img class="idcard-head" src="data:image/png;base64,${settings.fileData}" style="max-width: 100%; max-height: 100%;">
                            </div>
                        </div>
                    `

                    dialog.appendChild(container);

                    var cancelBtn = document.createElement('button');
                    cancelBtn.textContent = '取消';
                    cancelBtn.setAttribute('style', 'width: 60px; height: 32px; position: absolute; bottom: 0; right: 0; background-color: #f2f3f5; color: #4e5969; border: none; border-radius: 2px;');
                    cancelBtn.onmouseover = function() {
                        cancelBtn.style.backgroundColor = '#e6e8eb';
                    };
                    cancelBtn.onmouseout = function() {
                        cancelBtn.style.backgroundColor = '#f2f3f5'; 
                    }
                    cancelBtn.onclick = function() {
                        cancelBtn.disabled = true;
                        submitBtn.disabled = true;
                        self.ws.send(JSON.stringify({ method: 'VideoStop', args: {} }));
                        self.ws.last_method = "VideoStop";
                    };
                    container.appendChild(cancelBtn);

                    var submitBtn = document.createElement('button');
                    submitBtn.textContent = '比对';
                    submitBtn.setAttribute('style', 'position: absolute; bottom: 0; right: 0; width: 60px; height: 32px; margin-left: 32px; background-color: #165dff; color: #ffffff; border: none; border-radius: 2px;');
                    submitBtn.onmouseover = function() {
                        submitBtn.style.backgroundColor = '#0940c9'; 
                    }
                    submitBtn.onmouseout = function() {
                        submitBtn.style.backgroundColor = '#165dff'; 
                    }
                    submitBtn.onclick = function() {
                        cancelBtn.disabled = true;
                        submitBtn.disabled = true;
                        self.ws.onmessage = function(event) {
                            var response = JSON.parse(event.data);
                            if (response.method === 'VideoStop') {
                                self.ws.send(JSON.stringify({ method: 'FaceValidateWithTwoPhotos', args: { fileForm: 1, file1Data: preview.src.replace('data:image/png;base64,', ''), file2Data: settings.fileData, outTimes: settings.outTimes } }));
                                self.last_method = 'FaceValidateWithTwoPhotos';
                            } else if (response.method === 'FaceValidateWithTwoPhotos') {
                                self.removeElement(mask);
                                self.removeElement(dialog);
    
                                self.restoreScreen();

                                if (response.retVal === 0) {
                                    if (self.debug) {
                                        if (response.score > 0.7) {
                                            self.toast({ type:'success', message: 'FaceValidateWithPhoto核对通过' });
                                        } else {
                                            self.toast({ type: 'info', message: 'FaceValidateWithPhoto核验不通过: 相似度' + response.score });
                                        }
                                    }
                                    resolve({
                                        method: 'FaceValidateWithPhoto',
                                        retVal: response.retVal,
                                        score: response.score,
                                        scencePicBase64: preview.src.replace('data:image/png;base64,', ''),
                                        errMsg: '成功'
                                    })
                                } else if (response.retVal === -9) {
                                    response.retVal = -91;
                                    if (self.debug) {
                                        self.toast({ type: 'info', message: 'FaceValidateWithPhoto已撤销操作' });
                                    }
                                    reject(response);
                                } else {
                                    if (self.debug) {
                                        self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                    }
                                    reject(response);
                                }
                            }
                        }
                        self.ws.send(JSON.stringify({ method: 'VideoStop', args: {} }));
                        self.last_method = 'VideoStop';
                    };
                    submitBtn.disabled = true;

                    document.body.appendChild(mask);
                    document.body.appendChild(dialog);
                        
                    self.ws.onmessage = function(event) {
                        var response = JSON.parse(event.data);
                        if (response.method === 'VideoStart') {
                            if (response.retVal === 0) {
                                cancelBtn.style.right = '72px';
                                container.appendChild(submitBtn);
                                submitBtn.disabled = false;
                            } else {
                                self.restoreScreen();

                                if (self.debug) {
                                    self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                                }
                                reject(response);
                            }
                        } else if (response.method === 'VideoStream') {
                            preview.src = 'data:image/png;base64,' + response.imgBase64;
                        } else if (response.method === 'VideoStop') {
                            self.removeElement(mask);
                            self.removeElement(dialog);

                            self.restoreScreen();

                            if (self.debug) {
                                self.toast({ type: 'info', message: 'FaceValidateWithPhoto用户已取消操作' });
                            }
                            reject({ method: 'FaceValidateWithPhoto', retVal: -91, errMsg: '用户已取消操作' });
                        }
                    };

                    self.ws.send(JSON.stringify({"method": "VideoStart", "args": {"cameraNo": 2, "isEdgeDetection": 0}}));
                    self.last_method = "VideoStart";
                }

                if (settings.shootType === 1) {
                    usbDeviceFunc(resolve, reject);
                } else if (settings.shootType === 2) {
                    openDialog(self, resolve, reject);
                } else if (self.has_android_facecamera && self.has_android_facesdk) {
                    usbDeviceFunc(resolve, reject);
                } else if (self.has_android_facecamera && !self.has_android_facesdk) {
                    openDialog(self, resolve, reject);
                } else if (!self.has_android_facecamera) {
                    openDialog(self, resolve, reject);
                } else {
                    self.busy = false;
                    if (self.enable_computer_screen) {
                        self.StartComputerScreen();
                    }
                    if (self.debug) {
                        self.toast({ type: 'error', message: '不支持的调用方式, 请检测模块是否正常' });
                    }
                    reject(new Error('不支持的调用方式, 请检测模块是否正常')); 
                }
            });
        };

        // 照片比对
        this.FaceValidateWithTwoPhotos = function(options) {
            const self = this;
            self.current_method = 'FaceValidateWithTwoPhotos';
            var settings = $.extend({outTimes: 60, shootType: 0, fileForm: 1}, this.settings, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'FaceValidateWithTwoPhotos', args: settings };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'FaceValidateWithTwoPhotos') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            if (self.debug) {
                                if (response.score > 0.7) {
                                    self.toast({ type:'success', message: 'FaceValidateWithTwoPhotos核对通过' });
                                } else {
                                    self.toast({ type: 'info', message: 'FaceValidateWithTwoPhotos核验不通过: 相似度' + response.score });
                                }
                            }
                            resolve({
                                method: 'FaceValidateWithTwoPhotos',
                                retVal: response.retVal,
                                score: response.score,
                                errMsg: '成功'
                            })
                        } else if (response.retVal === -9) {
                            response.retVal = -91;
                            if (self.debug) {
                                self.toast({ type: 'info', message: 'FaceValidateWithTwoPhotos已撤销操作' });
                            }
                            reject(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '核验失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                }

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            })
        }

        // 高拍仪
        this.StartGPY = function(options) {
            const self = this;
            self.current_method = 'StartGPY';
            var settings = $.extend({cameraNo: 1, isEdgeDetection: 1}, options);
            if (settings.cameraNo !== 1) {
                settings.isEdgeDetection = 0;
            }
            this.resolutionList = [];
            this.currentResolution = '';
            return this.handle((resolve, reject) => {
                var previews = self.getPreviewElements(settings);

                for (let i = 0; i < previews.length; i++) {
                    previews[i].src = self.camera_poster;
                }

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'CamInit') {
                        self.ws.send(JSON.stringify({ method: 'CamGetResolutionList', args: settings }));
                    } else if (response.method === 'CamGetResolutionList') {
                        if (response.retVal == 0) {
                            self.resolutionList = response.resolutionList.split('|');
                            self.ws.send(JSON.stringify({ method: 'VideoStart', args: settings }));
                            self.last_method = 'VideoStart';
                        } else {
                            self.busy = false;
                            if (self.enable_computer_screen) {
                                self.StartComputerScreen();
                            }

                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '获取失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else if (response.method === 'VideoStart') {
                        if (response.retVal === 0) {
                            self.ws.send(JSON.stringify({ method: 'CamGetCurrentResolution', args: {} }));
                        } else {
                            self.busy = false;
                            if (self.enable_computer_screen) {
                                self.StartComputerScreen();
                            }

                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '启动失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else if (response.method === 'CamGetCurrentResolution') {
                        if (response.retVal == 0) {
                            self.currentResolution = response.resolution;
                            setTimeout(() => {
                                if (self.debug) {
                                    self.toast({ type: 'success', message: 'StartCamera启动成功' });
                                }
                                resolve({
                                    method: 'StartCamera',
                                    retVal: 0,
                                    resolutionList: self.resolutionList,
                                    currentResolution: self.currentResolution
                                });
                            }, 800);
                        } else {
                            // TODO 关闭摄像头并报错获取分辨率失败
                        }
                    } else if (response.method === 'VideoStream') {
                        if (response.imgBase64 != null && response.imgBase64 != '') {
                            for (let i = 0; i < previews.length; i++) {
                                previews[i].src = "data:image/jpeg;base64," + response.imgBase64;
                            }
                        }
                    }
                };
                
                self.ws.send(JSON.stringify({ method: 'CamInit', args: {} }));
                self.last_method = 'CamInit';
            });
        };
        
        // 旋转
        this.RotateGPY = function(options) {
            const self = this;
            self.current_method = 'RotateGPY';
            var settings = $.extend({angle: 0}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'CamSetRotateAngle', args: settings };

                const old = self.ws.onmessage
                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'CamSetRotateAngle') {
                        self.ws.onmessage = old;
                        if (response.retVal === 0) {
                            response.method = 'RotateGPY';
                            if (self.debug) {
                                self.toast({ type: 'success', message: 'RotateGPY执行成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else {
                        old(event);
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            }, false);
        };

		// 设置裁切
		this.SetCutMode = function(options) {
		    const self = this;
		    self.current_method = 'SetCutMode';
		    var settings = $.extend({angle: 0}, options);
			settings.cutType = settings.isEdgeDetection
		    return this.handle((resolve, reject) => {
		        var jsonObject = { method: 'CamSetCutType', args: settings };
		
		        const old = self.ws.onmessage
		        self.ws.onmessage = function(event) {
		            var response = JSON.parse(event.data);
		            if (response.method === 'CamSetCutType') {
		                self.ws.onmessage = old;
		                if (response.retVal === 0) {
		                    response.method = 'SetCutMode';
		                    if (self.debug) {
		                        self.toast({ type: 'success', message: 'SetCutMode执行成功' });
		                    }
		                    resolve(response);
		                } else {
		                    if (self.debug) {
		                        self.toast({ type: 'error', message: self.last_method + '失败: '+ response.errMsg });
		                    }
		                    reject(response);
		                }
		            } else {
		                old(event);
		            }
		        };
		
		        self.ws.send(JSON.stringify(jsonObject));
		        self.last_method = jsonObject.method;
		    }, false);
		};

        // 拍照
        this.ShootGPY = function(options={}) {
            const self = this;
            self.current_method = 'ShootGPY';
            var settings = $.extend({imagePath: ''}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'VideoGetImage', args: settings };

                const old = self.ws.onmessage
                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'VideoGetImage') {
                        self.ws.onmessage = old;
                        if (response.retVal === 0) {
                            response.method = 'ShootGPY';
                            if (self.debug) {
                                self.toast({ type:'success', message: 'ShootGPY执行成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    } else {
                        old(event);
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            }, false);
        };
        this.shoot = function(options={}) {
            const self = this;
            self.current_method = 'ShootGPY';
            var settings = $.extend({imagePath: ''}, options);
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'VideoGetImage', args: settings };

                const old = self.ws.onmessage
                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'VideoGetImage') {
                        self.ws.onmessage = old;
                        if (response.retVal === 0) {
                            response.method = 'ShootGPY';
                            if (self.debug) {
                                self.toast({ type:'success', message: 'ShootGPY执行成功' });
                            }
                            resolve(response.imgBase64);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '失败: '+ response.errMsg });
                            }
                        }
                    } else {
                        old(event);
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            }, false);
        };

        this.CloseGPY = function(options) {
            const self = this;
            self.current_method = 'CloseGPY';
            return this.handle((resolve, reject) => {
                var jsonObject = { method: 'VideoStop', args: {} };

                self.ws.onmessage = function(event) {
                    var response = JSON.parse(event.data);
                    if (response.method === 'VideoStop') {
                        self.restoreScreen();

                        if (response.retVal === 0) {
                            response.method = 'CloseGPY';
                            if (self.debug) {
                                self.toast({ type:'success', message: 'CloseGPY执行成功' });
                            }
                            resolve(response);
                        } else {
                            if (self.debug) {
                                self.toast({ type: 'error', message: self.last_method + '失败: '+ response.errMsg });
                            }
                            reject(response);
                        }
                    }
                };

                self.ws.send(JSON.stringify(jsonObject));
                self.last_method = jsonObject.method;
            }, false);
        };

        this.CancelOpt = function() {
            this.ws.send(JSON.stringify({ method: 'XG_CancelOpt_NoResp_EJG', args: {} }));
            this.busy = false;
        };

        // 工具方法

        this.toast = function(options) {
            // 创建toast容器
            var toastContainer = document.createElement('div');
            toastContainer.style.cssText = 'position:fixed;bottom:64px;left:50%;transform:translateX(-50%);padding:8px 16px;border-radius:4px;color:#fff;font-size:14px;z-index:9999;opacity:0;transition:opacity 0.3s ease-in-out;';
            
            // 设置不同类型的背景色
            var bgColor = '#64748b'; // 默认info类型
            if (options.type === 'success') {
                bgColor = '#22c55e';
            } else if (options.type === 'error') {
                bgColor = '#ef4444';
            }
            toastContainer.style.backgroundColor = bgColor;
            
            // 设置提示内容
            toastContainer.textContent = options.message || '';
            
            // 添加到页面
            document.body.appendChild(toastContainer);
            
            // 显示动画
            setTimeout(function() {
                toastContainer.style.opacity = '1';
            }, 10);
            
            // 3秒后自动消失
            setTimeout(function() {
                toastContainer.style.opacity = '0';
                setTimeout(function() {
                    document.body.removeChild(toastContainer);
                }, 300);
            }, 3000);
        }

        this.getPreviewElements = function(settings) {
            if (settings.hasOwnProperty('element')) {
                var previews = settings.element;
                try {
                    let a = $(previews)
                    if (a.length > 0) {
                        previews = []
                        for (let i = 0; i < a.length; i++) {
                            // 判断a[i]是div还是img
                            if (a[i].tagName === 'DIV') {
                                a[i].innerHTML = '';
                                var img = document.createElement('img');
                                a[i].appendChild(img);
                                previews.push(img)
                            } else if (a[i].tagName === 'IMG') {
                                previews.push(a[i]) 
                            }
                        }
                    } else {
                        previews = [] 
                    }
                } catch (error) {
                    previews = []
                }
            } else {
                var previews = []
            }
            return previews;
        };

        this.createMask = function() {
            // 创建遮罩层
            var mask = document.createElement('div');
            mask.style.position = 'fixed';
            mask.style.top = '0';
            mask.style.left = '0';
            mask.style.width = '100%';
            mask.style.height = '100%';
            mask.style.backgroundColor = 'rgba(0, 0, 0, 0.5)';
            mask.style.zIndex = '2048';
            return mask;
        };

        this.removeElement = function(element) {
            try {
                if (element) {
                    document.body.removeChild(element);
                }
            } catch (error) {
                console.error('移除元素失败:', error);
            }
        };

        this.restoreScreen = function() {
            this.busy = false;
            if (this.enable_computer_screen) {
                this.StartComputerScreen();
            }
        }
    }

    // 初始化方法
    EwpPlug.prototype.init = function(options) {
        this.settings = $.extend(this.settings, options);
        return this;
    };

})(jQuery);
